#include "SchmidtCAM.h"

int load_ccd290_drive_config_params(   char *cfg_fname, 
                                       ccd290_drive_config *cfg ){
    printf("|--> loading configuration parameters for CCD290 drive from: \n\t%s\n",
            cfg_fname );

    dictionary *ccd_drv_ini;
    ccd_drv_ini = iniparser_load( cfg_fname );
    
    if( ccd_drv_ini == NULL ){
        fprintf(stderr, "|##> cannot parse file; %s\n", cfg_fname);
        return -1;
    }

//	保存参数所在文件名
	sprintf(cfg->config_file, "%s", cfg_fname);

//  
    cfg->vtrans_num         = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:vtrans_num", 4700);
    cfg->vtrans_skip_num    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:vtrans_skip_num", 0);
    cfg->htrans_num		    = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:htrans_num", 1250);

//  读取垂直转移参数
    cfg->imgCLK1_cnt_min    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK1_cnt_min", 9000);
    cfg->imgCLK1_cnt_max    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK1_cnt_max", 21000);
    
    cfg->imgCLK2_cnt_min    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK2_cnt_min", 3000);
    cfg->imgCLK2_cnt_max    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK2_cnt_max", 15000);
    
    cfg->imgCLK3_cnt_min    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK3_cnt_min", 9000);
    cfg->imgCLK3_cnt_max    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK3_cnt_max", 21000);
    
    cfg->imgCLK4_cnt_min    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK4_cnt_min", 3000);
    cfg->imgCLK4_cnt_max    = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLK4_cnt_max", 15000);

    cfg->imgCLKx_cnt_MAX	= iniparser_getint(ccd_drv_ini, "CCD_VTRANS:imgCLKx_cnt_MAX", 29000);
    
    cfg->vtrans_state_cnt_max = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:vtrans_state_cnt_max", 305);

    cfg->ddr_data_rdy_cnt_max = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:ddr_data_rdy_cnt_max", 3);

    cfg->bias_ctr_cnt_min   = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:bias_ctr_cnt_min", 2000);
    cfg->bias_ctr_cnt_max   = iniparser_getint(ccd_drv_ini, "CCD_VTRANS:bias_ctr_cnt_max", 27000);


    cfg->phi1_cnt_min   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi1_cnt_min", 120);
    cfg->phi1_cnt_max   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi1_cnt_max", 225);
    
    cfg->phi2_cnt_min   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi2_cnt_min", 25);
    cfg->phi2_cnt_max   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi2_cnt_max", 220);
    
    cfg->phi3_cnt_min   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi3_cnt_min", 20);
    cfg->phi3_cnt_max   = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:phi3_cnt_max", 125);
    
    cfg->rst_cnt_min    = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:rst_cnt_min", 0);
    cfg->rst_cnt_max    = iniparser_getint(ccd_drv_ini, "CCD_HTRANS:rst_cnt_max", 40);

//  DELAY_CTRL
    cfg->delay_sel      = iniparser_getint(ccd_drv_ini, "DELAY_CTRL:delay_sel", 4);
    cfg->ddr_addr_sel   = iniparser_getint(ccd_drv_ini, "DELAY_CTRL:ddr_addr_sel", 29);
    cfg->sample_cnt_min = iniparser_getint(ccd_drv_ini, "DELAY_CTRL:sample_cnt_min", 0);

    cfg->VB_cnt_min     = iniparser_getint(ccd_drv_ini, "VB_HTRANS:VB_cnt_min", 0);
    cfg->VB_cnt_max     = iniparser_getint(ccd_drv_ini, "VB_HTRANS:VB_cnt_max", 0);

    iniparser_freedict(ccd_drv_ini);

	return 0;
}

/*
int copy_ccd290_drive_config_params( ccd290_drive_config *cfg_src, 
                                     ccd290_drive_config *cfg_dest ){

	cfg_dest->RT_phi1_a	= cfg_src->RT_phi1_a;
	cfg_dest->RT_phi1_b	= cfg_src->RT_phi1_b;

	cfg_dest->RT_phi2_a	= cfg_src->RT_phi2_a;
	cfg_dest->RT_phi2_b	= cfg_src->RT_phi2_b;

	cfg_dest->RT_phi3_a	= cfg_src->RT_phi3_a;
	cfg_dest->RT_phi3_b	= cfg_src->RT_phi3_b;

	cfg_dest->RT_rst_a	= cfg_src->RT_rst_a;
	cfg_dest->RT_rst_b	= cfg_src->RT_rst_b;

	cfg_dest->RT_reg_trans_num = cfg_src->RT_reg_trans_num;

	cfg_dest->LT_ad9106_trig_cnt_max 	= cfg_src->LT_ad9106_trig_cnt_max;
	cfg_dest->LT_line_trans_num 		= cfg_src->LT_line_trans_num;
	cfg_dest->LT_line_skip_num			= cfg_src->LT_line_skip_num;

	return 0;
}

*/

int extract_ccd290_drive_config_params( ccd290_drive_config *cfg, 
                                        uint32_t *reg_vals ){
    //  要特别注意这些参数定义的顺序，必须与PL端的配置参数的顺序保持一致
	reg_vals[0]	    = cfg->vtrans_num;         // n_row
	reg_vals[1]     = cfg->vtrans_skip_num;
	reg_vals[2]     = cfg->htrans_num;         // n_col

	reg_vals[3]	    = cfg->imgCLK1_cnt_min;
	reg_vals[4]     = cfg->imgCLK1_cnt_max;

	reg_vals[5]	    = cfg->imgCLK2_cnt_min;
	reg_vals[6]	    = cfg->imgCLK2_cnt_max;

	reg_vals[7]     = cfg->imgCLK3_cnt_min;
	reg_vals[8]     = cfg->imgCLK3_cnt_max;

	reg_vals[9]     = cfg->imgCLK4_cnt_min;
	reg_vals[10]    = cfg->imgCLK4_cnt_max;

	reg_vals[11]    = cfg->imgCLKx_cnt_MAX;

    reg_vals[12]    = cfg->bias_ctr_cnt_min;
    reg_vals[13]    = cfg->bias_ctr_cnt_max;

    reg_vals[14]    = cfg->phi1_cnt_min;
    reg_vals[15]    = cfg->phi1_cnt_max;
    reg_vals[16]    = cfg->phi2_cnt_min;
    reg_vals[17]    = cfg->phi2_cnt_max;
    reg_vals[18]    = cfg->phi3_cnt_min;
    reg_vals[19]    = cfg->phi3_cnt_max;
    reg_vals[20]    = cfg->rst_cnt_min;
    reg_vals[21]    = cfg->rst_cnt_max;

    reg_vals[22]    = cfg->vtrans_state_cnt_max;

    // reg_vals[23]    = cfg->ddr_data_rdy_cnt_max;
    // reg_vals[24]    = cfg->delay_sel;
    // reg_vals[25]    = cfg->ddr_addr_sel;
    // reg_vals[26]    = cfg->sample_cnt_min;

    // reg_vals[23]    = cfg->delay_sel;
    // reg_vals[24]    = cfg->ddr_addr_sel;
    // reg_vals[25]    = cfg->sample_cnt_min;

    reg_vals[23]    = cfg->ddr_data_rdy_cnt_max;

    reg_vals[24]    = cfg->delay_sel;
    reg_vals[25]    = cfg->ddr_addr_sel;

    reg_vals[26]    = cfg->sample_cnt_min;

    reg_vals[27]    = cfg->VB_cnt_min;
    reg_vals[28]    = cfg->VB_cnt_max;

#if defined(_DEBUG_CCD_DRV_PARAMS_)
    printf("(ccd290_drive_config)> extracted parameters ...\n");

    int i;
    for( i=0; i<CCD290_DRV_CONFIG_PARAM_NUM; i++ ){
        printf("reg_vals[%2d] = %10d\n", i, reg_vals[i]);
    }
#endif

	return 0;
}

int free_ccd290_drive_config_params( ccd290_drive_config *cfg_src ){
    // do nothing
    return 0;
};

int print_ccd290_drive_config_params( ccd290_drive_config *cfg ){

	printf("\n************************************************\n");
	printf("\tCCD290 drive config params:\n");
	printf("> vtrans_num            = %8d\n", cfg->vtrans_num);
	printf("> vtrans_skip_num       = %8d\n", cfg->vtrans_skip_num);
	printf("> htrans_num            = %8d\n", cfg->htrans_num);

    printf("> imgCLK1_cnt_min       = %8d\n", cfg->imgCLK1_cnt_min);
    printf("> imgCLK1_cnt_max       = %8d\n", cfg->imgCLK1_cnt_max);
    printf("> imgCLK2_cnt_min       = %8d\n", cfg->imgCLK2_cnt_min);
    printf("> imgCLK2_cnt_max       = %8d\n", cfg->imgCLK2_cnt_max);
    printf("> imgCLK3_cnt_min       = %8d\n", cfg->imgCLK3_cnt_min);
    printf("> imgCLK3_cnt_max       = %8d\n", cfg->imgCLK3_cnt_max);
    printf("> imgCLK4_cnt_min       = %8d\n", cfg->imgCLK4_cnt_min);
	printf("> imgCLK4_cnt_max       = %8d\n", cfg->imgCLK4_cnt_max);
    printf("> imgCLKx_cnt_MAX       = %8d\n", cfg->imgCLKx_cnt_MAX);

    printf("> vtrans_state_cnt_max  = %8d\n", cfg->vtrans_state_cnt_max);

    printf("> ddr_data_rdy_cnt_max  = %8d\n", cfg->ddr_data_rdy_cnt_max);

    printf("> phi1_cnt_min          = %8d\n", cfg->phi1_cnt_min);
    printf("> phi1_cnt_max          = %8d\n", cfg->phi1_cnt_max);
    printf("> phi2_cnt_min          = %8d\n", cfg->phi2_cnt_min);
    printf("> phi2_cnt_max          = %8d\n", cfg->phi2_cnt_max);
    printf("> phi3_cnt_min          = %8d\n", cfg->phi3_cnt_min);
    printf("> phi3_cnt_max          = %8d\n", cfg->phi3_cnt_max);
    printf("> rst_cnt_min           = %8d\n", cfg->rst_cnt_min);
    printf("> rst_cnt_max           = %8d\n", cfg->rst_cnt_max);

    printf("> delay_sel             = %8d\n", cfg->delay_sel);
    printf("> ddr_addr_sel          = %8d\n", cfg->ddr_addr_sel);

    printf("> sample_cnt_min        = %8d\n", cfg->sample_cnt_min);

    printf("> VB_cnt_min            = %8d\n", cfg->VB_cnt_min);
    printf("> VB_cnt_max            = %8d\n", cfg->VB_cnt_max);

	printf("\n");
	printf("> Note: the parameters are loaded from: %s\n", cfg->config_file);
	printf("************************************************\n\n");

	return 0;
}

int get_scan_param_from_ini( char *ini_file, int *skip_num, int *trans_num ){
    
    dictionary *scan_ini;
    scan_ini = iniparser_load(ini_file);
    
    *skip_num   = iniparser_getint( scan_ini, "CCD290_SCAN:skip_num", -1 );
    *trans_num  = iniparser_getint( scan_ini, "CCD290_SCAN:trans_num", -4700 ); 
    
    if( *skip_num < 0 || *trans_num < 0 ){
        printf("#==> Error happened when setting skip_num ot trans_num!\n");
        printf("#==> *skip_num  = %d\n", *skip_num);
        printf("#==> *trans_num = %d\n", *trans_num);
        exit(0);
    }
    
    iniparser_freedict(scan_ini);
    
    return 0;
}
